home *** CD-ROM | disk | FTP | other *** search
- #include <conio.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <graphics.h>
- #include <math.h>
- #include <alloc.h>
-
- #define TOL 0.0005
- #define PI 3.14159265358979323846
- #define X_AXIS 1
- #define Y_AXIS 2
- #define Z_AXIS 3
-
-
- typedef struct {
- float far x,y,z;
- } POINT3D;
-
- typedef struct {
- int x,y;
- } POINTint;
-
-
- /* World Limits in 2D */
- float WXleft;
- float WXright;
- float WYtop;
- float WYbottom;
-
- /* Device Limits */
- int DXmin;
- int DYmin;
- int DYmax;
- int DXmax;
-
- /* Rotations for 3D View in Radians*/
- float RX;
- float RY;
- float RZ;
- float COSRX;
- float SINRX;
- float COSRY;
- float SINRY;
- float COSRZ;
- float SINRZ;
-
-
-
- void InitGraphics(void);
- float DegToRad(float deg);
- float RadToDeg(float rad);
- POINT3D World3DToWorld2D(POINT3D p);
- POINTint World2DToDevice(POINT3D p);
- void drawpoint(POINT3D p1);
- void drawline(POINT3D p1,POINT3D p2);
- void drawaxis(void);
- void SetAxesAngles(float rx, float ry, float rz);
- void LoadAFile(char *str);
- void SaveAFile(char *str);
- float Coordinate(int i);
- void InitBezierCube(void);
- void GetMaxima(float *xi,float *xf,
- float *yi,float *yf,
- float *zi,float *zf);
- void ScaleBezierCube(float x, float y, float z);
- void DrawBezierCube(void);
- void FreezeBezierCube(float x,float y,float z);
- float UVW(float vmin, float vmax, float value);
- float Bernstein(float t, int i);
- POINT3D GetBezierPoint(float u, float v, float w);
- void RotatePatch(int patch, int axis, float deg);
- void TranslatePatch(int patch, int axis, float d);
- void ScalePatch(int patch, int axis, float s);
- void GoFFD(void);
- void drawObjects(int n);
- void SetView(void);
-
- POINT3D Cube[4][4][4];
- POINT3D far *Object;
- POINT3D far *Object2;
- #define MAXFACES 600 // object may have up to 2000 faces
- // COMPILE USING LARGE MEMORY MODEL
- int PointNum;
- float XS,YS,ZS;
-
-
- void main()
- {
- POINT3D p;
- int i, loop;
- float xmin, xmax,
- ymin, ymax,
- zmin, zmax;
-
- if((Object = (POINT3D *)farcalloc(3*MAXFACES, sizeof(POINT3D))) == NULL) {
- closegraph();
- printf("ERROR: Can't allocate database!\n");
- exit(1);
- }
-
- if((Object2 = (POINT3D *)farcalloc(3*MAXFACES, sizeof(POINT3D))) == NULL) {
- closegraph();
- printf("ERROR: Can't allocate database!\n");
- exit(1);
- }
-
- LoadAFile("bottle.raw");
- //LoadAFile("plate.raw");
-
- InitGraphics();
- setbkcolor(WHITE);
- setcolor(BROWN);
- cleardevice();
- /* World Limits */
- WXleft = -1.4;
- WXright = 1.4;
- WYtop = 1.4;
- WYbottom = -1.4;
-
- InitBezierCube();
- GetMaxima(&xmin,&xmax,&ymin,&ymax,&zmin,&zmax);
- ScaleBezierCube(xmax, ymax, zmax);
- FreezeBezierCube(xmax,ymax,zmax);
-
- SetView();
- drawObjects(1);
- DrawBezierCube();
-
- for(loop=0;loop<10;loop++) {
-
- InitBezierCube();
- ScaleBezierCube(xmax, ymax, zmax);
-
- // ANIMATION COMMANDS
-
- //USE WITH BOTTLE.RAW
- RotatePatch(3, Z_AXIS, loop*5.0);
- TranslatePatch(3, Y_AXIS, 0.5);
- TranslatePatch(3, X_AXIS,-0.1*loop);
-
- RotatePatch(0, Z_AXIS, -loop*5.0);
- TranslatePatch(0, Y_AXIS, -0.5);
- TranslatePatch(0, X_AXIS, -0.1*loop);
-
- /*
- // USE WITH PLATE.RAW
- RotatePatch(3, Y_AXIS, loop*9.0);
- RotatePatch(2, Y_AXIS, loop*4.5);
- RotatePatch(1, Y_AXIS, loop*2.0);
- */
- // END OF ANIMATION COMMANDS
-
- GoFFD();
- clearviewport();
- drawaxis();
- drawObjects(2);
- DrawBezierCube();
- }
- printf("\7");
- getch();
- closegraph();
- }
-
- /* /////////////////////////////////////////////////////// */
- void SetView(void) {
- int d;
-
- DXmin = 0.0;
- DYmin = 0.0;
- DYmax = getmaxy();
- DXmax = getmaxy();
- d = (getmaxx() - getmaxy())/2;
- setviewport(d,0,getmaxy()+d,getmaxy(),1);
- SetAxesAngles(20, -15, -5);
- drawaxis();
- }
-
-
-
- void drawObjects(int n) {
- int i;
-
- setcolor(BROWN);
- if (n==1)
- for(i=0;i<PointNum;i+=3) {
- drawline(Object[i],Object[i+1]);
- drawline(Object[i+1],Object[i+2]);
- drawline(Object[i+2],Object[i]);
- }
- else
- for(i=0;i<PointNum;i+=3) {
- drawline(Object2[i],Object2[i+1]);
- drawline(Object2[i+1],Object2[i+2]);
- drawline(Object2[i+2],Object2[i]);
- }
- }
-
-
- void GoFFD(void) {
- int i;
- float Xuvw, Yuvw, Zuvw;
- for(i=0;i<PointNum;i++) {
- Xuvw = UVW(-XS, XS, Object[i].x);
- Yuvw = UVW(-YS, YS, Object[i].y);
- Zuvw = UVW(-ZS, ZS, Object[i].z);
- Object2[i] = GetBezierPoint(Xuvw, Yuvw, Zuvw);
- }
- }
-
- void ScalePatch(int patch, int axis, float s){
- int i,k;
-
- for(k=0;k<4;k++)
- for(i=0;i<4;i++)
- switch(axis) {
- case X_AXIS: Cube[i][patch][k].x *= s; break;
- case Y_AXIS: Cube[i][patch][k].y *= s; break;
- case Z_AXIS: Cube[i][patch][k].z *= s; break;
- }
-
- }
-
-
-
- void TranslatePatch(int patch, int axis, float d){
- int i,k;
-
- for(k=0;k<4;k++)
- for(i=0;i<4;i++)
- switch(axis) {
- case X_AXIS: Cube[i][patch][k].x += d; break;
- case Y_AXIS: Cube[i][patch][k].y += d; break;
- case Z_AXIS: Cube[i][patch][k].z += d; break;
- }
-
- }
-
- void RotatePatch(int patch, int axis, float deg) {
- float xc=0.0, yc=0.0, zc=0.0;
- float COS, SIN;
- int i,j,k;
- POINT3D p, ptemp;
-
- deg = DegToRad(deg);
- COS = cos(deg);
- SIN = sin(deg);
-
- //find centroid of patch
- for(k=0;k<4;k++)
- for(i=0;i<4;i++) {
- xc += Cube[i][patch][k].x;
- yc += Cube[i][patch][k].y;
- zc += Cube[i][patch][k].z;
- }
-
- //divide by 16 to get center (average)
- xc /= 16.0;
- yc /= 16.0;
- zc /= 16.0;
-
- // translate center of patch to origin
- for(k=0;k<4;k++)
- for(i=0;i<4;i++) {
- Cube[i][patch][k].x -= xc;
- Cube[i][patch][k].y -= yc;
- Cube[i][patch][k].z -= zc;
- }
-
- // now that center of patch is at origin, rotate about axis
- for(k=0;k<4;k++)
- for(i=0;i<4;i++) {
- p = Cube[i][patch][k];
- switch(axis) {
- case X_AXIS:
- ptemp.x = p.x;
- ptemp.y = COS*p.y - SIN*p.z;
- ptemp.z = SIN*p.y + COS*p.z;
- Cube[i][patch][k] = ptemp;
- break;
- case Y_AXIS:
- ptemp.x = COS*p.x + SIN*p.z;
- ptemp.y = p.y;
- ptemp.z = -SIN*p.x + COS*p.z;
- Cube[i][patch][k] = ptemp;
- break;
- case Z_AXIS:
- ptemp.x = COS*p.x - SIN*p.y;
- ptemp.y = SIN*p.x + COS*p.y;
- ptemp.z = p.z;
- Cube[i][patch][k] = ptemp;
- break;
- }
- }
- // translate center of patch back to original place
- for(k=0;k<4;k++)
- for(i=0;i<4;i++) {
- Cube[i][patch][k].x += xc;
- Cube[i][patch][k].y += yc;
- Cube[i][patch][k].z += zc;
- }
-
- }
-
-
- float UVW(float vmin, float vmax, float value) {
- return( (value - vmin)/(vmax - vmin) );
- }
-
- float Bernstein(float t, int i) {
- float v;
- switch(i) {
- case 0: v = pow((1.0 - t),3); break;
- case 1: v = 3 * t * pow((1.0 - t),2); break;
- case 2: v = 3 * pow(t,2) * (1.0 - t); break;
- case 3: v = pow(t,3); break;
- }
- return(v);
- }
-
- POINT3D GetBezierPoint(float u, float v, float w) {
- int i,j,k;
- POINT3D q;
- float factor, wk, vk, wkvk;
-
- q.x = q.y = q.z = 0.0;
- for(k=0;k<4;k++) {
- wk = Bernstein(w,k);
- for(j=0;j<4;j++) {
- vk = Bernstein(v,j);
- wkvk = wk * vk;
- for(i=0;i<4;i++) {
- factor = Bernstein(u,i) * wkvk;
- q.x += Cube[i][j][k].x * factor;
- q.y += Cube[i][j][k].y * factor;
- q.z += Cube[i][j][k].z * factor;
- }
- }
- }
- return(q);
- }
-
- void FreezeBezierCube(float x,float y,float z) {
-
- XS = x;
- YS = y;
- ZS = z;
- }
-
- void GetMaxima(float *xi,float *xf,
- float *yi,float *yf,
- float *zi,float *zf) {
- int i;
- float x1=1e6,x2=-1e6,
- y1=1e6,y2=-1e6,
- z1=1e6,z2=-1e6;
-
- for(i=0;i<PointNum;i++) {
-
- if(Object[i].x < x1)
- x1 = Object[i].x;
- else
- if(Object[i].x > x2)
- x2 = Object[i].x;
-
- if(Object[i].y < y1)
- y1 = Object[i].y;
- else
- if(Object[i].y > y2)
- y2 = Object[i].y;
-
- if(Object[i].z < z1)
- z1 = Object[i].z;
- else
- if(Object[i].z > z2)
- z2 = Object[i].z;
- }
- *xi = x1;
- *xf = x2;
- *yi = y1;
- *yf = y2;
- *zi = z1;
- *zf = z2;
- }
-
- float Coordinate(int i) {
- switch(i) {
- case 0: return(-1.0);
- case 1: return(-0.3);
- case 2: return( 0.3);
- default: return( 1.0); //case 3
- }
- }
-
- void InitBezierCube(void) {
- int i,j, k;
-
- for(k=0;k<4;k++)
- for(j=0;j<4;j++)
- for(i=0;i<4;i++) {
- Cube[i][j][k].x = Coordinate(i);
- Cube[i][j][k].y = Coordinate(j);
- Cube[i][j][k].z = Coordinate(k);
- }
- }
-
- void ScaleBezierCube(float x, float y, float z) {
- int i,j, k;
-
- for(k=0;k<4;k++)
- for(j=0;j<4;j++)
- for(i=0;i<4;i++) {
- Cube[i][j][k].x *= x;
- Cube[i][j][k].y *= y;
- Cube[i][j][k].z *= z;
- }
- }
-
- void DrawBezierCube(void) {
- int i,j, k;
-
-
- setlinestyle(DOTTED_LINE,1, 1);
- setcolor(RED);
-
- for(k=0;k<4;k++)
- for(j=0;j<4;j++)
- for(i=0;i<4;i++)
- drawpoint(Cube[i][j][k]);
-
- for(j=0;j<4;j++)
- for(k=0;k<4;k++)
- for(i=0;i<3;i++)
- drawline(Cube[i][j][k],Cube[i+1][j][k]);
-
- for(j=0;j<4;j++)
- for(i=0;i<4;i++)
- for(k=0;k<3;k++)
- drawline(Cube[i][j][k],Cube[i][j][k+1]);
-
- for(k=0;k<4;k++)
- for(i=0;i<4;i++)
- for(j=0;j<3;j++)
- drawline(Cube[i][j][k],Cube[i][j+1][k]);
- setlinestyle(SOLID_LINE,1, 1);
- }
-
- void SaveAFile(char *str)
- {
- FILE *fptr;
- int i;
- if ((fptr = fopen(str,"w+t")) == NULL)
- printf("\7");
- else {
- for(i=0;i<PointNum;i+=3)
- fprintf(fptr,"%g %g %g %g %g %g %g %g %g\n",
- Object2[i].x, Object2[i].y, Object2[i].z,
- Object2[i+1].x, Object2[i+1].y, Object2[i+1].z,
- Object2[i+2].x, Object2[i+2].y, Object2[i+2].z);
- fclose(fptr);
- }
- }
-
-
- void LoadAFile(char *str)
- {
- FILE *fptr;
- float x,y,z;
- int bnum;
- if ( (fptr = fopen(str,"r")) == NULL) {
- printf("\7");
- }
- else {
- bnum = -1;
- while (!feof(fptr)) {
- if ((fscanf(fptr,"%f",&x) > 0) &&
- (fscanf(fptr,"%f",&y) > 0) &&
- (fscanf(fptr,"%f",&z) > 0)) {
- bnum++;
- if(bnum < MAXFACES*3) {
- Object[bnum].x = x;
- Object[bnum].y = y;
- Object[bnum].z = z;
- }
- }
- }
- fclose(fptr);
- PointNum = bnum+1;
- }
- }
-
-
-
- void InitGraphics(void)
- {
- int gdriver = DETECT, gmode, errorcode;
- initgraph(&gdriver, &gmode, "");
- if (gdriver != VGA) {
- printf("VGA graphics card required.\n");
- exit(1);
- }
- errorcode = graphresult();
- if (errorcode != grOk) /* an error occurred */
- {
- printf("Graphics error: %s\n", grapherrormsg(errorcode));
- printf("Press any key to halt:");
- getch();
- exit(1); /* terminate with an error code */
- }
- setviewport(0,0,getmaxx(),getmaxy(),1);
- }
-
- float DegToRad(float deg)
- {
- return(deg*PI/180.0);
- }
-
- float RadToDeg(float rad)
- {
- return(rad*180.0/PI);
- }
-
- void SetAxesAngles(float rx, float ry, float rz) {
- RX = DegToRad(rx);
- RY = DegToRad(ry);
- RZ = DegToRad(rz);
- COSRX = cos(RX);
- SINRX = sin(RX);
- COSRY = cos(RY);
- SINRY = sin(RY);
- COSRZ = cos(RZ);
- SINRZ = sin(RZ);
- }
-
-
-
- POINT3D World3DToWorld2D(POINT3D p)
- {
- POINT3D ptemp;
- ptemp = p;
- if (RX) {
- ptemp.x = p.x;
- ptemp.y = COSRX*p.y - SINRX*p.z;
- ptemp.z = SINRX*p.y + COSRX*p.z;
- p = ptemp;
- }
- if (RY) {
- ptemp.x = COSRY*p.x + SINRY*p.z;
- ptemp.y = p.y;
- ptemp.z = -SINRY*p.x + COSRY*p.z;
- p = ptemp;
- }
- if (RZ) {
- ptemp.x = COSRZ*p.x - SINRZ*p.y;
- ptemp.y = SINRZ*p.x + COSRZ*p.y;
- ptemp.z = p.z;
- }
- if (fabs(ptemp.x) < TOL) ptemp.x = 0.0;
- if (fabs(ptemp.y) < TOL) ptemp.y = 0.0;
- if (fabs(ptemp.z) < TOL) ptemp.z = 0.0;
- return(ptemp);
- }
-
- POINTint World2DToDevice(POINT3D p)
- {
-
- POINTint ptemp;
- ptemp.x = (WXleft-p.x)*(DXmax-DXmin)/(WXleft-WXright) + DXmin + 0.5;
- ptemp.y = (WYtop-p.y)*(DYmax-DYmin)/(WYtop-WYbottom) + DYmin + 0.5;
- return(ptemp);
-
- }
-
- void drawpoint(POINT3D p1)
- {
- /* draws a 3D point */
- POINTint p2;
- p1.z = -p1.z;
- p2 = World2DToDevice(World3DToWorld2D(p1));
- rectangle(p2.x - 2, p2.y - 2, p2.x + 2, p2.y + 2);
- }
-
- void drawline(POINT3D p1,POINT3D p2)
- {
- /* draws a 3D line */
- POINTint p11,p22;
- p1.z = -p1.z;
- p2.z = -p2.z;
- p11 = World2DToDevice(World3DToWorld2D(p1));
- p22 = World2DToDevice(World3DToWorld2D(p2));
- line(p11.x,p11.y,p22.x,p22.y);
- }
-
- void drawaxis(void) {
- POINT3D p1,p2;
-
- p1.x = p1.y = p1.z = 0;
-
- p2.x = 1; p2.y = 0; p2.z=0;
- setcolor(RED);
- drawline(p1,p2);
-
- p2.x = 0; p2.y = 1; p2.z=0;
- setcolor(GREEN);
- drawline(p1,p2);
-
- p2.x = 0; p2.y = 0; p2.z=1;
- setcolor(BLUE);
- drawline(p1,p2);
-
- setcolor(WHITE);
- }
-